#include "PlanService.h"
#include "log.h"
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QTextStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QStringConverter>
#endif

PlanService& PlanService::instance()
{
    static PlanService instance;
    return instance;
}

PlanService::PlanService(QObject *parent)
    : QObject(parent)
    , m_reminderTimer(new QTimer(this))
{
    // 设置提醒检查定时器（每30秒检查一次）
    m_reminderTimer->setInterval(30000);
    connect(m_reminderTimer, &QTimer::timeout, this, &PlanService::checkReminders);
    
    logInfo("PlanService 初始化完成");
}

PlanService::~PlanService()
{
    stopReminderCheck();
    logInfo("PlanService 已销毁");
}

// ========== 任务CRUD操作 ==========

PlanTask PlanService::createTask(const QString& title, const QDateTime& startTime, const QDateTime& endTime)
{
    PlanTask task(QUuid::createUuid().toString(), title);
    task.setStartTime(startTime);
    task.setEndTime(endTime);
    
    // 设置排序顺序（当前最大值+1）
    QDate date = startTime.date();
    QList<PlanTask> existingTasks = getTasks(date);
    int maxOrder = 0;
    for (const PlanTask& t : existingTasks) {
        if (t.getSortOrder() > maxOrder) {
            maxOrder = t.getSortOrder();
        }
    }
    task.setSortOrder(maxOrder + 1);
    
    if (m_storage.saveTask(task)) {
        logInfo("创建任务成功: " << task.getTitle());
        emit taskCreated(task);
        emit tasksUpdated(date);
        return task;
    } else {
        logError("创建任务失败: " << task.getTitle());
        return PlanTask(); // 返回无效任务
    }
}

bool PlanService::updateTask(const PlanTask& task)
{
    if (!task.isValid()) {
        logError("更新任务失败: 无效的任务对象");
        return false;
    }
    
    QDate date = task.getStartTime().date();
    if (!date.isValid()) {
        date = QDate::currentDate();
    }
    
    if (m_storage.saveTask(task)) {
        logInfo("更新任务成功: " << task.getTitle());
        emit taskUpdated(task);
        emit tasksUpdated(date);
        return true;
    } else {
        logError("更新任务失败: " << task.getTitle());
        return false;
    }
}

bool PlanService::deleteTask(const QString& taskId, const QDate& date)
{
    if (m_storage.deleteTask(taskId, date)) {
        logInfo("删除任务成功: " << taskId);
        emit taskDeleted(taskId, date);
        emit tasksUpdated(date);
        return true;
    } else {
        logError("删除任务失败: " << taskId);
        return false;
    }
}

QList<PlanTask> PlanService::getTasks(const QDate& date)
{
    QList<PlanTask> tasks = m_storage.loadTasks(date);
    
    // 按sortOrder排序
    std::sort(tasks.begin(), tasks.end(), [](const PlanTask& a, const PlanTask& b) {
        return a.getSortOrder() < b.getSortOrder();
    });
    
    return tasks;
}

QList<PlanTask> PlanService::getWeekTasks()
{
    // 获取本周的开始和结束日期
    QDate today = QDate::currentDate();
    int dayOfWeek = today.dayOfWeek(); // 1 = Monday, 7 = Sunday
    
    QDate startDate = today.addDays(1 - dayOfWeek); // 本周一
    QDate endDate = startDate.addDays(6);            // 本周日
    
    return getTasksInRange(startDate, endDate);
}

QList<PlanTask> PlanService::getTasksInRange(const QDate& startDate, const QDate& endDate)
{
    return m_storage.loadTasksInRange(startDate, endDate);
}

// ========== 任务状态管理 ==========

bool PlanService::toggleTaskStatus(const QString& taskId, const QDate& date)
{
    PlanTask task = findTask(taskId, date);
    if (!task.isValid()) {
        logWarning("切换任务状态失败: 任务不存在 " << taskId);
        return false;
    }
    
    // 切换状态
    TaskStatus newStatus = (task.getStatus() == TaskStatus::Todo) 
                         ? TaskStatus::Completed 
                         : TaskStatus::Todo;
    task.setStatus(newStatus);
    
    bool success = updateTask(task);
    
    if (success && newStatus == TaskStatus::Completed) {
        logInfo("任务已完成: " << task.getTitle());
        emit taskCompleted(task);
    }
    
    return success;
}

bool PlanService::markTaskCompleted(const QString& taskId, const QDate& date)
{
    PlanTask task = findTask(taskId, date);
    if (!task.isValid()) {
        logWarning("标记任务完成失败: 任务不存在 " << taskId);
        return false;
    }
    
    task.setStatus(TaskStatus::Completed);
    bool success = updateTask(task);
    
    if (success) {
        logInfo("任务已完成: " << task.getTitle());
        emit taskCompleted(task);
    }
    
    return success;
}

// ========== 任务排序 ==========

bool PlanService::reorderTasks(const QDate& date, const QStringList& taskIds)
{
    QList<PlanTask> tasks = m_storage.loadTasks(date);
    
    // 创建ID到任务的映射
    QMap<QString, PlanTask> taskMap;
    for (const PlanTask& task : tasks) {
        taskMap[task.getId()] = task;
    }
    
    // 更新sortOrder
    for (int i = 0; i < taskIds.size(); ++i) {
        QString taskId = taskIds[i];
        if (taskMap.contains(taskId)) {
            taskMap[taskId].setSortOrder(i);
        }
    }
    
    // 保存更新后的任务列表
    QList<PlanTask> updatedTasks = taskMap.values();
    if (m_storage.saveTasks(date, updatedTasks)) {
        logInfo("任务排序已更新");
        emit tasksUpdated(date);
        return true;
    } else {
        logError("更新任务排序失败");
        return false;
    }
}

// ========== 提醒检查 ==========

void PlanService::startReminderCheck()
{
    m_reminderTimer->start();
    logInfo("提醒检查已启动");
}

void PlanService::stopReminderCheck()
{
    m_reminderTimer->stop();
    logInfo("提醒检查已停止");
}

void PlanService::checkReminders()
{
    // 检查今天和明天的任务
    QDate today = QDate::currentDate();
    QList<PlanTask> todayTasks = getTasks(today);
    QList<PlanTask> tomorrowTasks = getTasks(today.addDays(1));
    
    QList<PlanTask> allTasks = todayTasks + tomorrowTasks;
    
    for (const PlanTask& task : allTasks) {
        // 跳过已完成的任务和已提醒过的任务
        if (task.getStatus() == TaskStatus::Completed) {
            continue;
        }
        
        if (m_remindedTasks.contains(task.getId())) {
            continue;
        }
        
        // 检查是否需要提醒
        if (task.shouldRemindNow()) {
            logInfo("触发任务提醒: " << task.getTitle());
            emit taskReminderTriggered(task);
            m_remindedTasks.insert(task.getId());
        }
    }
    
    // 清理过期的提醒记录
    QSet<QString> validTaskIds;
    
    for (int i = -2; i <= 2; ++i) {
        QList<PlanTask> tasks = getTasks(today.addDays(i));
        for (const PlanTask& task : tasks) {
            validTaskIds.insert(task.getId());
        }
    }
    
    // 移除不存在的任务ID
    QSet<QString> toRemove;
    for (const QString& taskId : m_remindedTasks) {
        if (!validTaskIds.contains(taskId)) {
            toRemove.insert(taskId);
        }
    }
    
    for (const QString& taskId : toRemove) {
        m_remindedTasks.remove(taskId);
    }
}

bool PlanService::snoozeTask(const QString& taskId, const QDate& date, int minutes)
{
    if (minutes <= 0) return false;
    PlanTask task = findTask(taskId, date);
    if (!task.isValid()) {
        logWarning("稍后提醒失败: 任务不存在 " << taskId);
        return false;
    }
    QDateTime newReminder = QDateTime::currentDateTime().addSecs(minutes * 60);
    task.setReminder(true, newReminder);
    bool ok = updateTask(task);
    if (ok) {
        clearReminderFlag(taskId); // 允许后续再次提醒
        emit tasksUpdated(date);
        logInfo("任务已设置稍后提醒: " << task.getTitle() << " +" << minutes << "分钟");
    }
    return ok;
}

// ========== 导出/导入 ==========

/**
 * @brief [FDD-2025-03-021][AC-003] 流式导出任务到JSON，避免一次性加载所有任务到内存
 */
bool PlanService::exportTasksToJson(const QDate& startDate, const QDate& endDate, const QString& filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::WriteOnly)) {
        logError("导出JSON失败，无法写入: " << filePath);
        return false;
    }

    // 手动写入JSON结构，边读取边写入
    QTextStream ts(&f);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    ts.setEncoding(QStringConverter::Utf8);
#else
    ts.setCodec("UTF-8");
#endif

    // 写入JSON头部
    ts << "{\n";
    ts << "  \"version\": 1,\n";
    ts << "  \"startDate\": \"" << startDate.toString(Qt::ISODate) << "\",\n";
    ts << "  \"endDate\": \"" << endDate.toString(Qt::ISODate) << "\",\n";
    ts << "  \"tasks\": [\n";

    int taskCount = 0;
    bool firstTask = true;

    // 使用 forEachTask 流式遍历
    bool success = m_storage.forEachTask(startDate, endDate, [&](const PlanTask& task) -> bool {
        if (!firstTask) {
            ts << ",\n";
        }
        firstTask = false;

        // 将任务转换为JSON并写入（缩进2空格）
        QJsonDocument taskDoc(task.toJson());
        QString taskJson = QString::fromUtf8(taskDoc.toJson(QJsonDocument::Compact));
        ts << "    " << taskJson;

        taskCount++;
        return true; // 继续遍历
    });

    // 写入JSON尾部
    ts << "\n  ]\n";
    ts << "}\n";
    f.close();

    if (success) {
        logInfo("已导出任务到JSON: " << filePath << " 共" << taskCount << "条");
    } else {
        logError("导出JSON时遇到错误: " << filePath);
    }

    return success;
}

static QString escapeCsv(const QString& s) {
    QString out = s;
    if (out.contains('"')) out.replace("\"", "\"\"");
    if (out.contains(',') || out.contains('\n') || out.contains('"')) {
        out = '"' + out + '"';
    }
    return out;
}

/**
 * @brief [FDD-2025-03-021][AC-003] 流式导出任务到CSV，边读取边写入
 */
bool PlanService::exportTasksToCsv(const QDate& startDate, const QDate& endDate, const QString& filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
        logError("导出CSV失败，无法写入: " << filePath);
        return false;
    }

    QTextStream ts(&f);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    ts.setEncoding(QStringConverter::Utf8);
#else
    ts.setCodec("UTF-8");
#endif

    // 写入CSV头部
    ts << "id,title,description,completionNote,startTime,endTime,completedTime,status,hasReminder,reminderTime,sortOrder,createdTime,updatedTime" << "\n";

    int taskCount = 0;

    // 使用 forEachTask 流式遍历，逐行写入
    bool success = m_storage.forEachTask(startDate, endDate, [&](const PlanTask& t) -> bool {
        ts << escapeCsv(t.getId()) << ","
           << escapeCsv(t.getTitle()) << ","
           << escapeCsv(t.getDescription()) << ","
           << escapeCsv(t.getCompletionNote()) << ","
           << t.getStartTime().toString(Qt::ISODate) << ","
           << t.getEndTime().toString(Qt::ISODate) << ","
           << t.getCompletedTime().toString(Qt::ISODate) << ","
           << (t.getStatus() == TaskStatus::Completed ? 1 : 0) << ","
           << (t.hasReminder() ? 1 : 0) << ","
           << t.getReminderTime().toString(Qt::ISODate) << ","
           << t.getSortOrder() << ","
           << t.getCreatedTime().toString(Qt::ISODate) << ","
           << t.getUpdatedTime().toString(Qt::ISODate) << "\n";

        taskCount++;
        return true; // 继续遍历
    });

    f.close();

    if (success) {
        logInfo("已导出任务到CSV: " << filePath << " 共" << taskCount << "条");
    } else {
        logError("导出CSV时遇到错误: " << filePath);
    }

    return success;
}

/**
 * @brief [FDD-2025-03-021] 优化导入JSON，使用批量写回限制内存
 */
bool PlanService::importTasksFromJson(const QString& filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly)) {
        logError("导入JSON失败，无法打开: " << filePath);
        return false;
    }
    QByteArray data = f.readAll();
    f.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isObject()) {
        logError("导入JSON失败，格式错误");
        return false;
    }

    QJsonArray arr = doc.object()["tasks"].toArray();
    if (arr.isEmpty()) {
        logWarning("导入JSON：未找到任务数组");
    }

    // [FDD-2025-03-021][R-003] 按日期聚合，限制每批最多处理 200 条任务
    const int BATCH_SIZE = 200;
    QMap<QDate, QList<PlanTask>> byDate;
    int processedCount = 0;
    int totalCount = 0;

    for (const auto& v : arr) {
        if (!v.isObject()) continue;
        PlanTask t = PlanTask::fromJson(v.toObject());
        if (!t.isValid()) continue;

        QDate d = t.getStartTime().isValid() ? t.getStartTime().date() : QDate::currentDate();
        byDate[d].append(t);
        totalCount++;

        // 达到批次大小后，写入并清空
        if (totalCount - processedCount >= BATCH_SIZE) {
            for (auto it = byDate.begin(); it != byDate.end(); ++it) {
                if (!m_storage.saveTasks(it.key(), it.value())) {
                    logWarning("导入JSON: 保存日期" << it.key() << "的任务时出错");
                }
                processedCount += it.value().size();
            }
            byDate.clear();
            qDebug() << "[Import] Processed batch, total:" << processedCount;
        }
    }

    // 保存剩余任务
    bool allOk = true;
    for (auto it = byDate.begin(); it != byDate.end(); ++it) {
        if (!m_storage.saveTasks(it.key(), it.value())) {
            allOk = false;
        }
    }

    if (allOk) emit tasksUpdated(QDate::currentDate());
    logInfo("导入JSON完成: " << filePath << " 共" << totalCount << "条");
    return allOk;
}

/**
 * @brief [FDD-2025-03-021] 优化导入CSV，使用批量写回限制内存
 */
bool PlanService::importTasksFromCsv(const QString& filePath)
{
    QFile f(filePath);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
        logError("导入CSV失败，无法打开: " << filePath);
        return false;
    }

    QTextStream ts(&f);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    ts.setEncoding(QStringConverter::Utf8);
#else
    ts.setCodec("UTF-8");
#endif

    QString header = ts.readLine();

    // [FDD-2025-03-021][R-003] 批量处理限制，每批最多 200 条任务
    const int BATCH_SIZE = 200;
    QMap<QDate, QList<PlanTask>> byDate;
    int processedCount = 0;
    int totalCount = 0;

    while (!ts.atEnd()) {
        QString line = ts.readLine();
        if (line.trimmed().isEmpty()) continue;

        // 简单CSV解析（处理引号）
        QStringList cols; cols.reserve(14);
        QString cur; bool inQuote=false;
        for (int i=0;i<line.size();++i){
            QChar c=line[i];
            if (c=='"'){
                inQuote = !inQuote;
            } else if (c==',' && !inQuote){
                cols<<cur; cur.clear();
            } else {
                cur.append(c);
            }
        }
        cols<<cur;

        // 处理引号
        for (QString &c: cols){
            c=c.trimmed();
            if (c.startsWith('"')&&c.endsWith('"')&&c.size()>=2){
                c=c.mid(1,c.size()-2);
                c.replace("\"\"","\"");
            }
        }

        if (cols.size() < 13) continue;

        PlanTask t;
        t.setId(cols[0]);
        t.setTitle(cols[1]);
        t.setDescription(cols[2]);
        t.setCompletionNote(cols[3]);
        t.setStartTime(QDateTime::fromString(cols[4], Qt::ISODate));
        t.setEndTime(QDateTime::fromString(cols[5], Qt::ISODate));
        if (!cols[6].isEmpty()) t.setCompletedTime(QDateTime::fromString(cols[6], Qt::ISODate));
        t.setStatus(cols[7].toInt()==1? TaskStatus::Completed : TaskStatus::Todo);
        bool hasRem = cols[8].toInt()==1;
        QDateTime r = QDateTime::fromString(cols[9], Qt::ISODate);
        t.setReminder(hasRem, r);
        t.setSortOrder(cols[10].toInt());

        QDate d = t.getStartTime().isValid()? t.getStartTime().date() : QDate::currentDate();
        byDate[d].append(t);
        totalCount++;

        // 达到批次大小后，写入并清空
        if (totalCount - processedCount >= BATCH_SIZE) {
            for (auto it = byDate.begin(); it != byDate.end(); ++it) {
                if (!m_storage.saveTasks(it.key(), it.value())) {
                    logWarning("导入CSV: 保存日期" << it.key() << "的任务时出错");
                }
                processedCount += it.value().size();
            }
            byDate.clear();
            qDebug() << "[Import] Processed batch, total:" << processedCount;
        }
    }
    f.close();

    // 保存剩余任务
    bool allOk = true;
    for (auto it = byDate.begin(); it != byDate.end(); ++it) {
        if (!m_storage.saveTasks(it.key(), it.value())) {
            allOk = false;
        }
    }

    if (allOk) emit tasksUpdated(QDate::currentDate());
    logInfo("导入CSV完成: " << filePath << " 共" << totalCount << "条");
    return allOk;
}

// ========== 私有辅助方法 ==========

PlanTask PlanService::findTask(const QString& taskId, const QDate& date)
{
    QList<PlanTask> tasks = m_storage.loadTasks(date);
    
    for (const PlanTask& task : tasks) {
        if (task.getId() == taskId) {
            return task;
        }
    }
    
    return PlanTask(); // 返回无效任务
}

